package bgai.gamelogic;

import java.util.Arrays;
import java.util.Vector;

/**
 * Gestisce le informazioni riguardanti una singola punta (in inglese "point")
 * della tavola da gioco. Le informazioni necessarie per ogni point sono:
 * <ol>
 * 		<li>numero di checker presenti
 * 		<li>colore delle checker presenti
 * </ol>
 */
public class Point implements Cloneable {
	/**
	 * Indice di questo point. E' un valore compreso nell'intervallo [1-24]
	 */
	private int position;
	
	/**
	 * Colore dei checker presenti in questo point
	 */
	private CheckerColor color;
	/**
	 * Numero di checker presenti in questo point
	 */
	private int num;
	
	/**
	 * Crea un nuovo point copiandone uno gia' esistente
	 * @param p point da copiare
	 */
	public Point(Point p) {
		this(p.getPosition(), p.getColor(), p.getNum());
	}
	
	/**
	 * Copia un point gia' esistente.
	 * @param p istanza da copiare
	 */
	void copy(Point p) {
		position= p.position;
		color= p.color;
		num= p.num;
	}
	
	/**
	 * Crea un nuovo point inizializzandolo ai valori dati
	 * @param position posizione di questo point. Valore nell'intervallo [1-24]
	 * @param color
	 * @param num
	 */
	public Point(int position, CheckerColor color, int num) {
		// posizione
		if (position<1 || position>Backgammon.NUM_POINTS) {
			throw new IndexOutOfBoundsException("La posizione di un point deve essere nell'intervallo [1-24]");
		}
		this.position= position;
		
		// colore
		if (color==null && num!=0) {
			throw new NullPointerException("Il colore non puo' essere null se sono presenti dei checkers");
		}
		this.color = color;
		
		// numero
		if (num<0 || num>Backgammon.NUM_CHECKERS) {
			throw new RuntimeException("Il numero di checker ammissibili in un point e' compreso fra 0 e "+Backgammon.NUM_CHECKERS);
		}
		if (num==0) {
			this.color= null;
		}
		this.num = num;
	}
	
	/**
	 * Crea un nuovo point vuoto
	 * @param position posizione di questo point. Valore nell'intervallo [1-24]
	 */
	public Point(int position) {
		this(position, null, 0);
	}
	
	
	/**
	 * Colore dei checker presenti in questo point
	 * @return colore dei checker, null se il point e' vuoto
	 */
	public CheckerColor getColor() {
		return color;
	}

	/**
	 * Restituisce la posizione di questo point nella tavola
	 * @return valore nell'intervallo [1-24]
	 */
	public int getPosition() {
		return position;
	}
	
	/**
	 * Numero di checker presenti in questo point
	 * @return
	 */
	public int getNum() {
		return num;
	}

	/**
	 * Muove un checker fuori da questo point
	 * <p>
	 * NB: lascia visibilita' package
	 * @throws BadMoveException 
	 */
	void moveOut() throws PointException {
		if (num==0) {
			throw new PointException(this, "Movimento del checker, ma il point era vuoto");
		}
		num--;
		if (num==0) {
			this.color= null;
		}
	}
	
	/**
	 * Muove un checker dentro questo point<p>
	 * NB: lascia visibilita' package
	 * @param color colore del checker che si sta movendo
	 * @throws BadMoveException 
	 */
	void moveIn(CheckerColor color) throws PointException {
		if (this.color==null || this.color==color) {
			// questo point e' vuoto oppure ha dei checker dello stesso colore
			num++;
			this.color= color;
		} else if (num==1) {
			// colore diverso ma attualmente presente un solo checker: viene mangiato
			this.color=color;
		} else {
			throw new PointException(this, "Non puoi muovere in un point in cui sono presenti piu' di un checker di colore diverso al tuo");
		}
	}
	
	/**
	 * Restituisce true se questo point si trova nella home del colore dato.
	 *  <ul>
	 * 		<li>la casa del nero e' [1-6]
	 * 		<li>la casa del bianco e' [19-24]
	 *  </ul>
	 * @param color
	 * @return
	 */
	public boolean isHome(CheckerColor color) {
		if (color.isBlack()) {
			// [1-6]
			if (1<=position && position<=6) {
				return true;
			} else {
				return false;
			}
		} else {
			// [19-24]
			if (19<=position && position<=24) {
				return true;
			} else {
				return false;
			}
		}
		
	}
	
	/**
	 * Restituisce true se e' presente almeno un checker del colore dato
	 * @param color
	 * @return
	 */
	public boolean hasCheckers(CheckerColor color) {
		if (num>=1 && this.color.equals(color)) {
			return true;
		} else {
			return false;
		}
	}
	
	@Override
	public Object clone() {
		try {

			Point p = (Point) super.clone();
			return p;
			
		} catch (CloneNotSupportedException e) {
			// non accadra' mai
			throw new InternalError("Come puo' essere CloneNotSupportedException?");
		}
	}
	
	@Override
	public String toString() {
		String str;
		if (getNum()>0) {
			// pieno
			str= "point["+position+"]:" + color + "(" + num + ")";
		} else {
			str= "point["+position+"]: empty";
		}
		return str;
	}
}
